﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using ctem.kernel.logger;
using System.Globalization;

namespace ctem.gui
{
    public partial class frmCTEM : Form
    {
        Model model;
        // главная формочка
        //frmChart frm = new frmChart();
        
        FreqCharacteristicsForm frq_char_form = new FreqCharacteristicsForm();
        //static BackgroundWorker bw_CH = new BackgroundWorker();


        ModelSaveLoader saveloader;
        ctem.kernel.adbms.IModeller modeller;
        ConfigManager config;
        ctem.kernel.logger.ILogger logger;
        Dictionary<string, ImageList> types_images = new Dictionary<string, ImageList>();
        
        //это супер генераторная переменная - гарантия уникальности имен акторов :)
        int SuperNum = 0;

        bool ShiftCreation = false;//создание нескольких акторов за раз
        string SelectedActorClass="";
        string SelectedInstanceName = "";

        const string CTEM_Version = "0.9.0";

        #region Формочка

        public frmCTEM()
        {
            InitializeComponent();
            
            config = new ConfigManager();
            modeller = ctem.kernel.adbms.ModellerService.QueryModellerService(config.ResourceFolder);
            model = new Model(modeller, graphBox1.graph, "Model1");
            saveloader = new ModelSaveLoader(model, config);
            //saveloader = new ModelSaveLoader(model);
            logger = modeller.SyncSendCommand<ctem.kernel.logger.ILogger>("get logger ctem.gui");
            logger.WriteMessage(ctem.kernel.logger.MessagePriority.Info, "Version = " + CTEM_Version);
            logger.WriteMessage(ctem.kernel.logger.MessagePriority.Info, "Resource Folder" + config.ResourceFolder);

            LoadImages(config.ImagesFloder, config.KnowActorTypes);
            CreateTypeItems(config.KnowActorTypes);

            openFileDialog1.InitialDirectory = config.ModelsFolder;
            saveFileDialog1.InitialDirectory = config.ModelsFolder;

            //bw_CH.WorkerReportsProgress = true;
            ////bw.WorkerSupportsCancellation = true;
            //bw_CH.DoWork += bw_DoWork;
            //bw_CH.ProgressChanged += bw_ProgressChanged;
            ////bw.RunWorkerCompleted += bw_RunWorkerCompleted;




            graphBox1.Width = 5000;
            graphBox1.Height = 5000;

        }
        private void frmCTEM_FormClosed(object sender, FormClosedEventArgs e)
        {
            modeller.AsyncSendCommand("terminate");
            //Thread.Sleep(1000); //для отладки 
  
        }

        #endregion

        #region Собственные - вспомогательные

        private void LoadImages(string images_folger, List<ActorTypeConfig> actors_types)
        {
            foreach (ActorTypeConfig at in actors_types)
            {
                if (types_images.ContainsKey(at.TypeName) == false)
                {
                    ImageList ilist = new ImageList();
                    ilist.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
                    ilist.ImageSize = new System.Drawing.Size(81, 61);
                    ilist.TransparentColor = System.Drawing.Color.Transparent;
                    types_images.Add(at.TypeName, ilist);
                }
                types_images[at.TypeName].Images.Add(at.ClassName, Bitmap.FromFile(at.Icon));
                
            }
        }

        private void CreateTypeItems(List<ActorTypeConfig> actors_types_configs)
        {
            List<string> typesnames = ExctractKnowTypesNames(actors_types_configs);
            int i = 5;
            foreach (string name in typesnames)
            {
                RadioButton rb = new RadioButton();
                rb.AutoSize = true;
                rb.Text = name;
                rb.Top = i;
                rb.Left = 5;
                rb.CheckedChanged += new EventHandler(TypeRadioButton_CheckedChanged);
                TypesNamesPanel.Controls.Add(rb);
                i = i + rb.Height + 5;
            }

            if (TypesNamesPanel.Controls.Count != 0)
                if (TypesNamesPanel.Controls[0] is RadioButton)
                    ((RadioButton)TypesNamesPanel.Controls[0]).Checked = true;
        }

        List<string> ExctractKnowTypesNames(List<ActorTypeConfig> actors_types_configs)
        {
            List<string> knowtypesnames = new List<string>();
            foreach (ActorTypeConfig atc in actors_types_configs)
            {
                if (knowtypesnames.Contains(atc.TypeName) == false)
                    knowtypesnames.Add(atc.TypeName);
            }
            return knowtypesnames;
        }

        private void TypeRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            if(sender is RadioButton)
            {
                
                listViewElements.LargeImageList = types_images[((RadioButton)sender).Text];
                listViewElements.Items.Clear();
                for (int i = 0; i < listViewElements.LargeImageList.Images.Count; i++)
                {
                    //ListViewItem lvi = new ListViewItem("", i);
                    //listViewElements.LargeImageList.Images[i].ToString();
                    string ActorClass = listViewElements.LargeImageList.Images.Keys[i];
                    string VisName = "";
                    for (int j = 0; j < config.KnowActorTypes.Count; j++)
                        if (config.KnowActorTypes[j].ClassName == ActorClass) VisName = config.KnowActorTypes[j].VisibleName;
                    listViewElements.Items.Add(new ListViewItem(VisName, i));
                }
            }
        }


        #endregion

        #region GraphBox

        private void graphBox1_BeforeAddElement(GraphBuilder.Element item,  GraphBuilder.GraphBox.Graph gr)
        {
            SuperNum++;
            if (item is GraphBuilder.Vertex)
                
                if(SelectedActorClass!="")
                {
                    
                    ActorTypeConfig selected_actor = saveloader.FindByClassName(SelectedActorClass, config.KnowActorTypes);
                    string assem = selected_actor.Assembly;
                    string className = selected_actor.ClassName;
                    string instanceName = selected_actor.ClassName + SuperNum.ToString();
                    SelectedInstanceName = instanceName;
                    string visName=selected_actor.VisibleName;

                    modeller.AsyncSendCommand("new actor" + " " + " '" + assem + "' " + className + " " + instanceName);
                    
                    (item as GraphBuilder.Vertex).Name = instanceName;
                    (item as GraphBuilder.Vertex).ClassName = className;
                    (item as GraphBuilder.Vertex).VisibleName = visName;
                    (item as GraphBuilder.Vertex).HelpFile = selected_actor.HelpFile;
                    (item as GraphBuilder.Vertex).HelpPath = selected_actor.HelpPath;
                    List<string> inports = modeller.SyncSendCommand<List<string>>("get all inports " + instanceName);
                    foreach (string inp in inports)
                        gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.In, inp));
                    //gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.In, "SeqGenerator.inport"));

                    List<string> outports = modeller.SyncSendCommand<List<string>>("get all outports " + instanceName);
                    foreach (string outp in outports)
                        gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.Out, outp));
                    (item as GraphBuilder.Vertex).bitmap = new Bitmap(listViewElements.LargeImageList.Images[listViewElements.SelectedIndices[0]]);

                    if (SelectedActorClass == "ctem.samples.actors.sequential.CommonW")
                    {
                        CommonWForm form_CommonW = new CommonWForm();
                        form_CommonW.NameCommonW = instanceName;
                        form_CommonW.modeller = modeller;
                        form_CommonW.ShowDialog();

                    }

                    //если шифт был не нажат, то забываем что что-то создавали
                    if (!ShiftCreation)
                        SelectedActorClass = "";
                    
                }
            if (item is GraphBuilder.Edge)
            {
                //string name_dest = (item as GraphBuilder.Edge).toPort.Owner.ClassName;

                //if (name_dest != "ctem.samples.actors.sequential.Booster")
                    modeller.AsyncSendCommand("new link" + " " + " " + (item as GraphBuilder.Edge).fromPort.Name + " " + (item as GraphBuilder.Edge).toPort.Name);
                //else 
                //    if (gr.GetEdgesForPort((item as GraphBuilder.Edge).toPort).Count = 0)
                //        modeller.AsyncSendCommand("new link" + " " + " " + (item as GraphBuilder.Edge).fromPort.Name + " " + (item as GraphBuilder.Edge).toPort.Name);

                //modeller.SyncSendCommand<bool>("new link" + " " + " " + (item as GraphBuilder.Edge).fromPort.Name + " " + (item as GraphBuilder.Edge).toPort.Name);
               // if (item as GraphBuilder.Edge).toPort.Owner.ClassName ="ctem.samples.actors.concurrent.ChartActor" )

            }

        }

        private void graphBox1_BeforeRemoveElement(GraphBuilder.Element item, GraphBuilder.GraphBox.Graph gr)
        {
            if (item is GraphBuilder.Vertex)
            {
                //удаляем все входящие связи данного актора
                foreach (GraphBuilder.Port p in (item as GraphBuilder.Vertex).GetInPorts())
                    foreach (GraphBuilder.Edge e in gr.GetEdgesForPort(p))
                    {
                        modeller.AsyncSendCommand("del link " + e.fromPort.Name + " " + e.toPort.Name);
                    }

                //удаляем все исходящие связи данного актора
                foreach (GraphBuilder.Port p in (item as GraphBuilder.Vertex).GetOutPorts())
                    foreach (GraphBuilder.Edge e in gr.GetEdgesForPort(p))
                    {
                        modeller.AsyncSendCommand("del link " + e.fromPort.Name + " " + e.toPort.Name);
                    }

                modeller.AsyncSendCommand("del actor "+item.Name);
            }
            else
                if (item is GraphBuilder.Edge)
                {
                    modeller.AsyncSendCommand("del link " + (item as GraphBuilder.Edge).fromPort.Name + " " + (item as GraphBuilder.Edge).toPort.Name);
                }
        }

        // отображение параметров для выделенного элемента
        private void graphBox1_AfterChangeSelection(GraphBuilder.Element item, GraphBuilder.GraphBox.Graph gr)
        {
            ActorTypeConfig selected_actor = saveloader.FindByVisibleName(item.VisibleName, config.KnowActorTypes);

            //panelCommonW.Visible = false;
            dataGridView1.Rows.Clear();
            string[] l = new string[2];
            l[0] = "name";
            l[1] = item.Name;
            dataGridView1.Rows.Add(l);
            //имена акторов менять нельзя
            dataGridView1.Rows[0].ReadOnly = true;

            if (item is GraphBuilder.Vertex)
            {
                if (selected_actor.ClassName == "ctem.samples.actors.sequential.CommonW")
                {
                    SelectedInstanceName = item.Name;
                    btnEditWParams.Visible = true;
                    btnEditWParams.Left = dataGridView1.Left;
                    btnEditWParams.Top = dataGridView1.Bottom;
                    btnEditWParams.Width = dataGridView1.Width;

                }
                else
                {
                    btnEditWParams.Visible = false;
                    List<string> parameters = null;
                    parameters = modeller.SyncSendCommand<List<string>>("get all params " + item.Name);
                    
                    if (parameters.Count > 0)
                        for (int i = 0; i < parameters.Count; i++)
                        {
                            l[0] = parameters[i];
                            string param_type = modeller.SyncSendCommand<string>("get param type " + item.Name + "." + parameters[i]).ToString();
                            if (param_type == "string") l[1] = modeller.SyncSendCommand<string>("get param value " + item.Name + "." + parameters[i]).ToString();
                            else
                                if (param_type == "int") l[1] = modeller.SyncSendCommand<int>("get param value " + item.Name + "." + parameters[i]).ToString();
                                else
                                    if (param_type == "double") l[1] = modeller.SyncSendCommand<double>("get param value " + item.Name + "." + parameters[i]).ToString();
                                        //l[1] = modeller.SyncSendCommand<double>("get param name " + item.Name + "." + parameters[i]).ToString();
                            dataGridView1.Rows.Add(l);
                        }
                }
            }
            dataGridView1.Height = dataGridView1.ColumnHeadersHeight + dataGridView1.Rows.Count * dataGridView1.Rows[0].Height;
        }

        private void graphBox1_BeforePasteElement(GraphBuilder.Element item, GraphBuilder.GraphBox.Graph gr)
        {
            SuperNum++;
            ActorTypeConfig copied_actor = saveloader.FindByClassName(gr.CopiedItem.ClassName, config.KnowActorTypes);
            string assem = copied_actor.Assembly;
            string className = copied_actor.ClassName;
            string instanceName = copied_actor.ClassName + SuperNum.ToString();
            string visName = copied_actor.VisibleName;

            modeller.AsyncSendCommand("new actor" + " " + " '" + assem + "' " + className + " " + instanceName);

            (item as GraphBuilder.Vertex).Name = instanceName;
            (item as GraphBuilder.Vertex).ClassName = className;
            (item as GraphBuilder.Vertex).VisibleName = visName;
            (item as GraphBuilder.Vertex).HelpFile = copied_actor.HelpFile;
            (item as GraphBuilder.Vertex).HelpPath = copied_actor.HelpPath;
            List<string> inports = modeller.SyncSendCommand<List<string>>("get all inports " + instanceName);
            foreach (string inp in inports)
                gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.In, inp));
            //gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.In, "SeqGenerator.inport"));

            List<string> outports = modeller.SyncSendCommand<List<string>>("get all outports " + instanceName);
            foreach (string outp in outports)
                gr.AddElement(new GraphBuilder.Port(item as GraphBuilder.Vertex, GraphBuilder.TPortType.Out, outp));
            (item as GraphBuilder.Vertex).bitmap = gr.CopiedItem.bitmap;

            // установка скопированных параметров
            List<string> parameters = null;
            parameters = modeller.SyncSendCommand<List<string>>("get all params " + gr.CopiedItem.Name);
            if (parameters.Count > 0)
                for (int i = 0; i < parameters.Count; i++)
                {

                    string val = "";
                    string param_type = modeller.SyncSendCommand<string>("get param type " + gr.CopiedItem.Name + "." + parameters[i]).ToString();
                    if (param_type == "string") val = modeller.SyncSendCommand<string>("get param value " + gr.CopiedItem.Name + "." + parameters[i]).ToString();
                    else
                        if (param_type == "int") val = modeller.SyncSendCommand<int>("get param value " + gr.CopiedItem.Name + "." + parameters[i]).ToString();
                        else
                            if (param_type == "double") val = modeller.SyncSendCommand<double>("get param value " + gr.CopiedItem.Name + "." + parameters[i]).ToString();

                    //string val = modeller.SyncSendCommand<double>("get param value" + gr.CopiedItem.Name + "." + parameters[i]).ToString();
                    modeller.AsyncSendCommand("set param " + instanceName + "." + parameters[i] + " " + val);
                }


        }

        #endregion

        #region DataGrid

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            //try
            //{
                if (e.ColumnIndex != 0)
                {
                    //TODO: Ввести механизм обработки пользовательского ввода
                    //в будущем он перерастет в язык выражений
                    //а также систематизиронного сообщать пользователю об ошибка в вводе
                    //и не с помощью MessageBox'ov, а более деликатно
                    bool maybe = true;
                    string temps = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();//.Replace('.', CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()[0]);
                    string param_type = modeller.SyncSendCommand<string>("get param type " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()).ToString();
                    if (param_type != "string")
                    {
                        temps = temps.Replace(',', CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()[0]);
                        try
                        {
                            Convert.ToDouble(temps);
                        }
                        catch //(System.InvalidCastException)
                        {
                            maybe = false;
                        }
                    }
                    if (maybe)
                    {
                        dataGridView1.Rows[e.RowIndex].Cells[1].Value = temps;

                        if ((param_type == "int") || (param_type == "double"))
                        {
                            modeller.AsyncSendCommand("set param " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[e.RowIndex].Cells[0].Value + " " + dataGridView1.Rows[e.RowIndex].Cells[1].Value);
                            int temp = (int)System.Convert.ToDouble(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
                            trackBar1.Maximum = (int)Math.Ceiling((double)temp * 10 + 10);
                        }
                        else
                            if (param_type == "string") modeller.AsyncSendCommand("set param " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[e.RowIndex].Cells[0].Value + " " + '\'' + dataGridView1.Rows[e.RowIndex].Cells[1].Value + '\'');

                    }
                    else
                    {
                        if (param_type == "double")
                            dataGridView1.Rows[e.RowIndex].Cells[1].Value = modeller.SyncSendCommand<double>("get param value " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()).ToString();
                        if (param_type == "int")
                            dataGridView1.Rows[e.RowIndex].Cells[1].Value = modeller.SyncSendCommand<int>("get param value " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()).ToString();
                    }
                }
            //}
            //catch { }
        }


        private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {
            if ((e.Button == MouseButtons.Left) && (e.ColumnIndex == 1) && (e.RowIndex != 0))
            {
                EventHandler temp = new EventHandler(dataGridView1_SelectionChanged);
                temp.Invoke(this.dataGridView1, new EventArgs());
                
            }

        }

        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            trackBar1.Visible = false;
            dataGridView1.EndEdit();
        }

        private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            try
            {

                
                    if ((dataGridView1.SelectedCells.Count == 1) && (dataGridView1.SelectedCells[0].ColumnIndex == 1))
                        if (dataGridView1.SelectedCells[0].RowIndex != 0)
                    {
                        string param_type = modeller.SyncSendCommand<string>("get param type " + dataGridView1.Rows[0].Cells[1].Value.ToString() + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString()).ToString();

                        if ((param_type == "int") || (param_type == "double"))
                        {
                            trackBar1.Parent = dataGridView1;
                            trackBar1.Visible = true;

                            Rectangle rect = dataGridView1.GetCellDisplayRectangle(dataGridView1.SelectedCells[0].ColumnIndex, dataGridView1.SelectedCells[0].RowIndex, false);
                            trackBar1.Location = new Point(rect.Location.X, rect.Location.Y + rect.Height); ;
                            trackBar1.Width = rect.Width;
                            trackBar1.Height = rect.Height;

                            //string param_type = modeller.SyncSendCommand<string>("get param type " + dataGridView1.Rows[0].Cells[1].Value.ToString() + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString()).ToString();
                            if (param_type == "double")
                            {
                                double ttt = System.Convert.ToDouble(modeller.SyncSendCommand<double>("get param value " + dataGridView1.Rows[0].Cells[1].Value.ToString() + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString()) * 10);
                                trackBar1.Maximum = (int)Math.Ceiling((double)ttt + 10);
                                trackBar1.Value = (int)ttt;// trackBar1.Maximum;
                            }
                            else
                                if (param_type == "int")
                                {
                                    int ttt = System.Convert.ToInt32(modeller.SyncSendCommand<int>("get param value " + dataGridView1.Rows[0].Cells[1].Value.ToString() + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString()) * 10);
                                    trackBar1.Maximum = (int)Math.Ceiling((double)ttt + 10);
                                    trackBar1.Value = ttt;// trackBar1.Maximum;
                                }
                        }
                        else// параметр строковый
                        {
                            GraphBuilder.Vertex v = (graphBox1.graph.GetElementByName(dataGridView1.Rows[0].Cells[1].Value.ToString()) as GraphBuilder.Vertex);
                            if (v.ClassName == "ctem.samples.actors.sequential.Reporter")
                            {
                                saveFileDialog2.FileName = modeller.SyncSendCommand<string>("get param value " + dataGridView1.Rows[0].Cells[1].Value.ToString() + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString());
                                if (saveFileDialog2.ShowDialog() == DialogResult.OK)
                                {
                                    modeller.AsyncSendCommand("set param " + dataGridView1.Rows[0].Cells[1].Value.ToString() + ".FileName " + '\'' + saveFileDialog2.FileName + '\'');
                                }
                            }

                        }

                        // if (trackBar1.Maximum % 10 != 0) trackBar1.Maximum = (Math.Truncate(trackBar1.Maximum / 10) + 1) * 10;



                    }
            }
            catch (Exception exc)
            {
                throw (exc);
            }

        }

        #endregion

        #region TrackBar
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            string param_type = modeller.SyncSendCommand<string>("get param type " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString());
            if (param_type == "double")
                dataGridView1.SelectedCells[0].Value = (Convert.ToDouble(trackBar1.Value) / 10).ToString();
            else
                if (param_type == "int")
                    dataGridView1.SelectedCells[0].Value = Convert.ToInt32(trackBar1.Value/10);
            //dataGridView1.SelectedCells[0].Value = (Convert.ToDouble(trackBar1.Value)).ToString();
            modeller.AsyncSendCommand("set param " + dataGridView1.Rows[0].Cells[1].Value + "." + dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex].Cells[0].Value.ToString() + " " + dataGridView1.SelectedCells[0].Value.ToString());
            dataGridView1.EndEdit();
        }

        #endregion

        #region Менюшка

        private void mbtnDoCalcToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (model.model_state == Model.TModelState.Work)
            {
                logger.WriteMessage(MessagePriority.Info, "User press Pause button");
                modeller.AsyncSendCommand("pause");
                model.model_state = Model.TModelState.Pause;
                mbtnPauseContToolStripMenuItem.Text = "Продолжить";
                btnPauseCont.Text = "Продолжить";
            }
            else
            {
                logger.WriteMessage(MessagePriority.Info, "User press UnPause button");
                modeller.AsyncSendCommand("unpause");
                model.model_state = Model.TModelState.Work;
                mbtnPauseContToolStripMenuItem.Text = "Пауза";
                btnPauseCont.Text = "Пауза";
            }
        }


        private void mbtnStartStopToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (model.model_state == Model.TModelState.Stoped)
            {
                logger.WriteMessage(MessagePriority.Info, "User press Start button");
                modeller.AsyncSendCommand("online");
                modeller.AsyncSendCommand("start");
                model.model_state = Model.TModelState.Work;

                mbtnStartStopToolStripMenuItem.Text = "Остановить";
                btnStartStop.Text = "Остановить";
                mbtnPauseContToolStripMenuItem.Enabled = true;
                btnPauseCont.Enabled = true;

                button1.Enabled = false;
                offlineрасчетToolStripMenuItem.Enabled = false;

            }
            else
            {
                logger.WriteMessage(MessagePriority.Info, "User press Stop button");
                modeller.AsyncSendCommand("stop");
                model.model_state = Model.TModelState.Stoped;
                
                mbtnStartStopToolStripMenuItem.Text = "Начать";
                btnStartStop.Text = "Начать";
                mbtnStartStopToolStripMenuItem.Enabled = true;
                mbtnPauseContToolStripMenuItem.Enabled = false;
                btnStartStop.Enabled = true;
                btnPauseCont.Enabled = false;

                button1.Enabled = true;
                offlineрасчетToolStripMenuItem.Enabled = true;

            }
        }
        
        private void mbtnModelLoadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            logger.WriteMessage(MessagePriority.Info, "User press Load Model button");
            saveloader.ClearModel();
            //saveloader.LoadModel(@"C:\Documents and Settings\Root\Мои документы\qwerty.model", config);
            //saveloader.LoadModel(@"D:\1\1.model", config);
            //saveloader.LoadModel(@"D:\AbrEk\projects\Летние проекты\CTEM2\ctem.BugReport\2008.03.02\Ws.model", config);
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                saveloader.LoadModel(openFileDialog1.FileName, config);
                this.Text = "СТЕМ - " + openFileDialog1.FileName;
            }
            Refresh();
        }

        private void mbtnModelSaveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            logger.WriteMessage(MessagePriority.Info, "User press Save Model button");
            //saveloader.ClearModel();
            if (model.FileName != "")
                saveloader.SaveModel(model.FileName, config);
            else
                mbtnModelSaveAsToolStripMenuItem_Click(sender,e);
        }

        private void mbtnModelSaveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            logger.WriteMessage(MessagePriority.Info, "User press Save As Model button");
            //saveloader.SaveModel(@"D:\1\1.model", config);
            //saveloader.SaveModel(@"D:\AbrEk\projects\Летние проекты\CTEM2\ctem.gui\ctem.gui\bin\Debug\Resource\models\proba2.model", config); 
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                saveloader.SaveModel(saveFileDialog1.FileName, config);
                this.Text = "СТЕМ - " + saveFileDialog1.FileName;

            }

        }

        private void mbtmNewModel_Click(object sender, EventArgs e)
        {
            logger.WriteMessage(MessagePriority.Info, "User press New Model button");
            saveloader.ClearModel();
            graphBox1.Refresh();
            this.Text = "СТЕМ - Несохранённая модель";
        }

        private void offlineрасчетToolStripMenuItem_Click(object sender, EventArgs e)
        {
            logger.WriteMessage(MessagePriority.Info, "User press Offline-modelling button");
            frmOfflineProcessing offline = new frmOfflineProcessing(modeller, logger);
            offline.ShowDialog();
        }
          

        #endregion


        private void listViewElements_Click(object sender, EventArgs e)
        {

            if (listViewElements.FocusedItem!=null)
                SelectedActorClass = listViewElements.FocusedItem.ImageList.Images.Keys[listViewElements.FocusedItem.Index];
            /* как-то странно этот код работает - слишком зависит от того когда был нажат Шифт, решил пока вылкючить вообще
             * if (Control.ModifierKeys == Keys.Shift)
                ShiftCreation = true;
            else
                ShiftCreation = false;
             * */
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void mbtnShowActorNames_Click(object sender, EventArgs e)
        {
            graphBox1.graph.DrawVertexNames = mbtnShowActorNames.Checked;
            graphBox1.Refresh();
        }

        private void mbtnAddModelPartMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                saveloader.LoadModel(openFileDialog1.FileName, config);
            }
            Refresh();
        }

       
        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            modeller.AsyncSendCommand("set param ModelExecuter.Speed "+trackBar2.Value);
        }

        private void btnEditWParams_Click(object sender, EventArgs e)
        {
            CommonWForm form_CommonW = new CommonWForm();
            form_CommonW.NameCommonW = SelectedInstanceName;
            form_CommonW.modeller = modeller;
            form_CommonW.ShowDialog();
        }

        private void frmCTEM_Load(object sender, EventArgs e)
        {
            this.Text = "СТЕМ - Несохранённая модель";
        }

        private void frmCTEM_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            //if (e.KeyCode == Keys.Delete)
            //graphBox1_PreviewKeyDown(sender, e);

        }

        private void frmCTEM_KeyDown(object sender, KeyEventArgs e)
        {
            //if (!dataGridView1.Focused)
            graphBox1.KeyDn(sender, e);

        }



        private void RunHelpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, @".\Resource\help\CTEMHelp.chm", @".\Resource\help\CTEMHelp.chm::/introduction.htm");
        }

        private void Lab1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, @".\Resource\help\CTEMHelp.chm", @".\Resource\help\CTEMHelp.chm::/lab1.htm");
        }

        private void Lab2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, @".\Resource\help\CTEMHelp.chm", @".\Resource\help\CTEMHelp.chm::/lab2.htm");
        }

        private void Lab3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, @".\Resource\help\CTEMHelp.chm", @".\Resource\help\CTEMHelp.chm::/lab3.htm");
        }

        private void Lab4ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, @".\Resource\help\CTEMHelp.chm", @".\Resource\help\CTEMHelp.chm::/lab4.htm");
        }


        #region ЧХ

        private double[] CalcW_PartAmp(string st, double frq)
        {
            double[] res = new double[2];

            string[] temp_num = st.Split('|');
            //double part_amp = Math.Pow(Convert.ToDouble(temp_num[0]), 2);
            //double part_amp_j = 0.0;
            double part_Re = Convert.ToDouble(temp_num[0]);
            double part_Im = 0.0;
            if (temp_num.GetLength(0) > 1)
                for (int j = 1; j < temp_num.GetLength(0) - 1; j++)
                {
                    if (j % 2 == 0)
                        part_Re -= Convert.ToDouble(temp_num[j]) * Math.Pow(frq, j); 
                    else
                        part_Im += Convert.ToDouble(temp_num[j]) * Math.Pow(frq, j); 
                }
            res[0] = Math.Sqrt(part_Im * part_Im + part_Re * part_Re);
            //res[1] = Math.Atan(part_Im / part_Re);
            res[1] = Math.Atan2(part_Im, part_Re);

            return res;

        }

        private void CalcLogCH(object data)
        {
            List<GraphBuilder.Vertex> v_list = data as List<GraphBuilder.Vertex>;
            //double[] amps = new double[1000];
            //double[] phss = new double[1000];

            //lock (frq_char_form)
            //{
                int count = 0;
                for (double frq = 1; frq < 1000; frq++)
                {
                    double amp = 0; double phs = 0;
                    for (int i = 0; i < v_list.Count; i++)
                    {
                        switch (v_list[i].ClassName)
                        {
                            case "ctem.samples.actors.sequential.Booster":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double part_phs = 0.0;
                                    amp += (k > 0) ? 20 * Math.Log10(k) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }

                            case "ctem.samples.actors.sequential.InertiaLink":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double T = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T");
                                    double part_amp = k / Math.Sqrt(1 + frq * frq * T * T);
                                    double part_phs = -Math.Atan(frq * T);
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.Aperiodic2":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double T1 = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T1");
                                    double T2 = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T2");
                                    double part_amp = k / (Math.Sqrt(1 + frq * frq * T1 * T1) * Math.Sqrt(1 + frq * frq * T2 * T2));
                                    double part_phs = -Math.Atan(frq * T1) - Math.Atan(frq * T2);
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.Oscillator":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double T = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T");
                                    double d = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".d");
                                    double part_amp = k / Math.Sqrt(Math.Pow((1 - frq * frq * T * T), 2) + 4 * d * d * frq * frq * T * T);
                                    //double part_phs = -Math.Atan((2 * d * frq * T) / (1 - frq * frq * T * T));
                                    double part_phs = -Math.Atan2(2 * d * frq * T, 1 - frq * frq * T * T);


                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.Integrator":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double part_amp = k / frq;
                                    double part_phs = Math.PI / 2;
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.AperiodicIntegr":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double T = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T");
                                    double part_amp = k / (frq * Math.Sqrt(1 + frq * frq * T * T));
                                    double part_phs = Math.PI / 2 - Math.Atan(frq * T);
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.IdealDiff":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double part_amp = k * frq;
                                    double part_phs = -Math.PI / 2;
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.Diff":
                                {
                                    double k = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".k");
                                    double T = modeller.SyncSendCommand<double>("get param value " + v_list[i].Name + ".T");
                                    double part_amp = k * frq / Math.Sqrt(1 + frq * frq * T * T);
                                    double part_phs = -Math.PI / 2 - Math.Atan(frq * T);
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += -part_phs * 180 / Math.PI;
                                    break;
                                }
                            case "ctem.samples.actors.sequential.CommonW":
                                {
                                    string tt_str = modeller.SyncSendCommand<string>("get param value " + v_list[i].Name + ".stra");
                                    double[] part_a = CalcW_PartAmp(tt_str, frq);

                                    tt_str = modeller.SyncSendCommand<string>("get param value " + v_list[i].Name + ".strb");
                                    double[] part_b = CalcW_PartAmp(tt_str, frq);

                                    double part_amp = part_b[0] / part_a[0];
                                    double part_phs = part_b[1] - part_a[1];
                                    amp += (part_amp > 0) ? 20 * Math.Log10(part_amp) : 0;
                                    phs += part_phs * 180 / Math.PI;
                                    break;
                                }

                        }
                        count++;
                    }

                    //amps[count] = amp;
                    //phss[count] = phs;

                    frq_char_form.SetArrayOfData(frq, amp, phs);
                //}
                //frq_char_form.SetArrayOfData(amps, phss);
            }
            frq_char_form.can_close = true;
            
        }

        private void sss(object data)
        {
            CalcLogCH(data);
        }

        private void LCHToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // получение ЛАЧХ/ЛФЧХ

            frq_char_form.Show();
            frq_char_form.Clear();
            frq_char_form.can_close = false;

            Thread th = new Thread(new ParameterizedThreadStart(sss));
            List<GraphBuilder.Vertex> v_list = graphBox1.graph.GetAllVertex();
            th.Start(v_list);
        }

        #endregion ЧХ

    }
}
